package com.jahentao.integrationTest.case13;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
 * 
 * @author jahen
 * @date 2016年8月8日
 * @time 上午9:38:53
 * @category Socket编程
 */
public class DownloadService {
	
	private DownloadInfo downloadServiceInfo;
	private List<DownloadInfo> infoList;
	private MultiThreadDownloadJFrame frame;
	private DownloadThread[] threads;
	private int threadNum;
	private URL url;
	private String outPath;
	// 不用volatile也没关系，传递给各个线程的是引用，而且各个线程修改的部分不同
	private /*volatile*/ Properties properties;
	
	
	public List<DownloadInfo> getInfoList() {
		return infoList;
	}
	
	public Properties getProperties() {
		return properties;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	public DownloadService(DownloadInfo downloadInfo, MultiThreadDownloadJFrame frame){
		this.downloadServiceInfo = downloadInfo;
		this.frame = frame;
		init();
	}
	
	/*
	 * 用于断点续传的加载
	 */
	public DownloadService(Properties properties, MultiThreadDownloadJFrame frame){
		this.frame = frame;
		this.properties = properties;
		load();
	}

	/**
	 * 加载断点续传的文件信息
	 */
	private void load() {
		try {
			url = new URL(properties.getProperty("url"));
			threadNum = Integer.parseInt(properties.getProperty("threadNum"));
			outPath = properties.getProperty("outPath");
			
			// 填充下载信息
			infoList = new ArrayList<DownloadInfo>();
			for(int i=0; i<threadNum; i++){
				DownloadInfo info = new DownloadInfo();
				info.setIndex(i);
				info.setStart(Long.parseLong(properties.getProperty("thread."+i+".start"))); // start = amount
				info.setEnd(Long.parseLong(properties.getProperty("thread."+i+".end")));
				info.setAmount(Long.parseLong(properties.getProperty("thread."+i+".amount")));
				info.setUrl(url);
				info.setOutPath(outPath);
				info.setThreadNum(threadNum);
				
				infoList.add(info);
			}
			
			threads = new DownloadThread[threadNum];
			for(int i=0; i<threadNum; i++) { // 加载进度条
				threads[i] = new DownloadThread(infoList.get(i), frame, properties,true); // 新建线程
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

	private void init() {
		threadNum = downloadServiceInfo.getThreadNum();
		url = downloadServiceInfo.getUrl();
		outPath = downloadServiceInfo.getOutPath();
		String fileName = downloadServiceInfo.getMetadataFile().getName();  // 正确的文件名
		File metadataFile = new File(outPath + "/" + fileName+".download");
		downloadServiceInfo.setMetadataFile(metadataFile);
		URLConnection conn = null;
		// URL连接
		try {
			conn = url.openConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 获取文件大小
		long length = conn.getContentLengthLong();
		System.out.println("文件大小 : "+length);
		long onePartSize = length/threadNum;
		
		properties = new Properties();
		properties.setProperty("fileName", fileName);
		properties.setProperty("fileSize", ""+length);
		properties.setProperty("threadNum", ""+threadNum);
		properties.setProperty("metadataFile", metadataFile.getAbsolutePath());
		properties.setProperty("url", url.toString());
		properties.setProperty("outPath", outPath);
		
		// 计算下载信息
		infoList = new ArrayList<DownloadInfo>();
		for(int i=0; i<threadNum; i++){
			
			DownloadInfo info = new DownloadInfo();
			info.setUrl(url);
			info.setOutPath(outPath);
			info.setThreadNum(threadNum);
			info.setIndex(i);// 线程的i与bar[i]对应
			long start = i * onePartSize;
			info.setStart(start);
			long end;
			if(i<threadNum-1)
				end = (i+1)*onePartSize;
			else
				end = length;
			info.setEnd(end);
			infoList.add(info);
			
			// 记录下载信息
//			properties.setProperty("thread."+i+".index", ""+i);
			properties.setProperty("thread."+i+".start", ""+start);
			properties.setProperty("thread."+i+".end", ""+end);
			properties.setProperty("thread."+i+".amount", ""+0);// 初始时完成为0
			
			//写入属性
			try {
				metadataFile.getParentFile().mkdirs();
				synchronized(properties){
					if(metadataFile.exists())
						metadataFile.delete();
				}
				FileOutputStream fos = new FileOutputStream(metadataFile);
				properties.store(fos, "append thread "+i+" info");
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 开始复制
	 */
	@SuppressWarnings("deprecation")
	public void startCopy(boolean isPaused){
		if(isPaused) // 由暂停继续
			for(DownloadThread thread : threads) {
				thread.resume();
			}
		else{ // 从起始开始复制
			if(threads != null) { // 断点续传
				for(int i=0; i<threadNum; i++){
					threads[i].start();
				}
			}
			else{
				threads = new DownloadThread[threadNum];
				for(int i=0; i<threadNum; i++){
					threads[i] = new DownloadThread(infoList.get(i),frame,properties,false);
					threads[i].start();
				}
			}
		}
	}
	/**
	 * 暂停/取消 复制<br>
	 * @param isCancel false 就仅暂停，保存临时文件记录；true直接取消复制
	 */
	@SuppressWarnings("deprecation")
	public void pauseCopy(boolean isCancel){
		if(isCancel){ // 取消
			for(DownloadThread thread : threads){
				thread.interrupt();
			}
			// 同时把文件删除
			//throw new InterruptedException("复制取消");
		}
		else
			for(DownloadThread thread : threads){
				thread.suspend();
			}
	}
	
}
